﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Utility.PoolSystem;

namespace Utility.DataSystem
{
	public struct FieldActionParam
	{
		public decimal value;
		public string str;

		public FieldActionParam (decimal value) : this ()
		{
			this.value = value;
		}

		public FieldActionParam (string str) : this ()
		{
			this.str = str;
		}
	}

	public interface IFieldActionPerformer
	{
		string Name { get; }
		void PerformAction (IDataFieldContext context, FieldAction fieldAction, out bool isInterested);
	}

	public class FieldActionPerformers : IDisposable, IPoolCallback
	{
		static SimplePool<FieldActionPerformers> Pool { get; } = new SimplePool<FieldActionPerformers> (() => new FieldActionPerformers ());
		static HashSet<IFieldActionPerformer> RemoveSet { get; } = new HashSet<IFieldActionPerformer> ();

		public static FieldActionPerformers New () => Pool.Spawn ();

		public void Dispose ()
		{
			Pool.Despawn (this);
		}

		void IPoolCallback.OnSpawn ()
		{
			set.Clear ();
		}

		void IPoolCallback.OnDespawn ()
		{
			set.Clear ();
		}


		FieldActionPerformers () { }
		HashSet<IFieldActionPerformer> set = new HashSet<IFieldActionPerformer> ();

		public bool IsEmpty => set.Count == 0;

		public void Add (IFieldActionPerformer performer)
		{
			set.Add (performer);
		}

		public void Add (IEnumerable<IFieldActionPerformer> eerformers)
		{
			set.AddRange (eerformers);
		}

		public void PerformActionAndFilter (IDataFieldContext context, FieldAction fieldAction)
		{
			var msg = FieldCenter.GetDebugMsg (fieldAction);

			RemoveSet.Clear ();
			bool isInterested;
			foreach (var performer in set)
			{
				if (performer != null)
				{
					msg?.StartPerformer (performer);
					performer.PerformAction (context, fieldAction, out isInterested);

					if (!isInterested)
					{
						RemoveSet.Add (performer);
					}
					msg?.EndPerformer (performer, !isInterested);
				}
			}
			//filter
			RemoveSet.Add (null);
			set.ExceptWith (RemoveSet);
			RemoveSet.Clear ();
		}

		public void PerformAction (IDataFieldContext context, FieldAction fieldAction)
		{
			var msg = FieldCenter.GetDebugMsg (fieldAction);

			foreach (var performer in set)
			{
				msg?.StartPerformer (performer);
				performer.PerformAction (context, fieldAction, out _);
				msg?.EndPerformer (performer);
			}
		}
	}
}